import React from 'react';

import '@fortawesome/fontawesome-free/css/all.css';
import '@fortawesome/fontawesome-free/css/v4-shims.css';

import 'amis/lib/themes/antd.css';
import 'amis/lib/helper.css';
import 'amis/sdk/iconfont.css';

import axios from 'axios';
import copy from 'copy-to-clipboard';

import {AlertComponent, ToastComponent, render as renderAmis} from 'amis';
import {alert, confirm, toast} from 'amis-ui';
import {createHashHistory} from 'history';
import {match} from 'path-to-regexp/dist/index.js';
import {createRoot} from 'react-dom/client';

const history = createHashHistory();
function normalizeLink(to: string, location = history.location) {
    to = to || '';

    if (to && to[0] === '#') {
        to = location.pathname + location.search + to;
    } else if (to && to[0] === '?') {
        to = location.pathname + to;
    }

    const idx = to.indexOf('?');
    const idx2 = to.indexOf('#');
    let pathname = ~idx
        ? to.substring(0, idx)
        : ~idx2
            ? to.substring(0, idx2)
            : to;
    let search = ~idx ? to.substring(idx, ~idx2 ? idx2 : undefined) : '';
    let hash = ~idx2 ? to.substring(idx2) : location.hash;

    if (!pathname) {
        pathname = location.pathname;
    } else if (pathname[0] != '/' && !/^https?\:\/\//.test(pathname)) {
        let relativeBase = location.pathname;
        const paths = relativeBase.split('/');
        paths.pop();
        let m;
        while ((m = /^\.\.?\//.exec(pathname))) {
            if (m[0] === '../') {
                paths.pop();
            }
            pathname = pathname.substring(m[0].length);
        }
        pathname = paths.concat(pathname).join('/');
    }

    return pathname + search + hash;
}

function isCurrentUrl(to: string, ctx?: { strict: any; }) {
    if (!to) {
        return false;
    }
    const pathname = history.location.pathname;
    const link = normalizeLink(to, {
        ...history.location,
        pathname,
        hash: ''
    });

    if (!~link.indexOf('http') && ~link.indexOf(':')) {
        let strict = ctx && ctx.strict;
        return match(link, {
            decode: decodeURIComponent,
            strict: typeof strict !== 'undefined' ? strict : true
        })(pathname);
    }

    return decodeURI(pathname) === link;
}

// amis 环境配置
const env = {
    theme: 'antd',
    enableAMISDebug: true,
    // 下面三个接口必须实现
    fetcher: ({
                  url, // 接口地址
                  method, // 请求方法 get、post、put、delete
                  data, // 请求数据
                  responseType,
                  config, // 其他配置
                  headers // 请求头
              }: any) => {
        config = config || {};
        config.withCredentials = true;
        responseType && (config.responseType = responseType);

        if (config.cancelExecutor) {
            config.cancelToken = new (axios as any).CancelToken(
                config.cancelExecutor
            );
        }

        config.headers = headers || {};

        if (method !== 'post' && method !== 'put' && method !== 'patch') {
            if (data) {
                config.params = data;
            }
            return (axios as any)[method](url, config);
        } else if (data && data instanceof FormData) {
            config.headers = config.headers || {};
            config.headers['Content-Type'] = 'multipart/form-data';
        } else if (
            data &&
            typeof data !== 'string' &&
            !(data instanceof Blob) &&
            !(data instanceof ArrayBuffer)
        ) {
            data = JSON.stringify(data);
            config.headers = config.headers || {};
            config.headers['Content-Type'] = 'application/json';
        }

        return (axios as any)[method](url, data, config);
    },
    isCancel: (value: any) => (axios as any).isCancel(value),
    copy: (content: string) => {
        copy(content);
        toast.success('内容已复制到粘贴板');
    },
    updateLocation: (location: string, replace: any) => {
        location = normalizeLink(location);
        if (location === 'goBack') {
            return history.goBack();
        } else if (
            (!/^https?\:\/\//.test(location) &&
                location ===
                history.location.pathname + history.location.search) ||
            location === history.location.href
        ) {
            // 目标地址和当前地址一样，不处理，免得重复刷新
            return;
        } else if (/^https?\:\/\//.test(location) || !history) {
            return (window.location.href = location);
        }

        history[replace ? 'replace' : 'push'](location);
    },
    jumpTo: (to: string, action: { actionType: string; blank: boolean; }) => {
        if (to === 'goBack') {
            return history.goBack();
        }

        to = normalizeLink(to);

        if (isCurrentUrl(to)) {
            return;
        }

        if (action && action.actionType === 'url') {
            action.blank === false
                ? (window.location.href = to)
                : window.open(to, '_blank');
            return;
        } else if (action && action.blank) {
            window.open(to, '_blank');
            return;
        }

        if (/^https?:\/\//.test(to)) {
            window.location.href = to;
        } else if (
            (!/^https?\:\/\//.test(to) &&
                to === history.pathname + history.location.search) ||
            to === history.location.href
        ) {
            // do nothing
        } else {
            history.push(to);
        }
    },
    isCurrentUrl: isCurrentUrl,
    notify: (
      type: 'error' | 'success' /**/,
      msg: string /*提示内容*/
    ) => {
      toast[type]
        ? toast[type](msg, type === 'error' ? '系统错误' : '系统消息')
        : console.warn('[Notify]', type, msg);
    },
    alert,
    confirm,
};

const APPSchema = {
    type: 'app',
    brandName: 'Amis MultiPage',
    logo: '/logo.png',
    header: {

    },
    // footer: '<div class="p-2 text-center bg-light">底部区域</div>',
    // asideBefore: '<div class="p-2 text-center">菜单前面区域</div>',
    // asideAfter: '<div class="p-2 text-center">菜单后面区域</div>',
    api: '/api/pages/site.json'
}

let amisProps: any = {};
let scoped = {};
let container = document.getElementById('root');
function createElements(props: any, callback: any): any {
    amisProps = {
        ...amisProps,
        ...props,
        scopeRef: (ref: any) => {
            if (ref) {
                Object.assign(scoped, ref);
                callback?.();
            }
        }
    };

    return (
        <div className="amis-routes-wrapper">
            <ToastComponent
                position={(env && env.toastPosition) || 'top-center'}
                closeButton={false}
                timeout={5000}
                locale={props?.locale}
                theme={env?.theme}
            />
            <AlertComponent
                locale={props?.locale}
                theme={env?.theme}
                container={() => env?.getModalContainer?.() || container}
            />

            {renderAmis(APPSchema, amisProps, env)}
        </div>
    );
}

const root = createRoot(container);
root.render(createElements({
    location: history.location
}, ()=>{}));
history.listen(state => {
    root.render(createElements({
        location: state.location || state
    }));
});
